package dyl.sys.quartz;

import java.text.ParseException;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.scheduling.quartz.CronTriggerBean;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;

import dyl.common.util.JdbcTemplateUtil;
import dyl.sys.bean.SysQuartz;

/**
 * 定时器总管理
 * 
 * @author Dyl
 * 
 */
public class QuartzManager implements BeanFactoryAware {
	private Logger log = Logger.getLogger(QuartzManager.class);
	private Scheduler scheduler;
	private static BeanFactory beanFactory = null;
	@Resource
	private JdbcTemplateUtil jdbcTemplate;

	@SuppressWarnings("unused")
	private void reScheduleJob() throws Exception, ParseException {
		List<SysQuartz> sysQuartzList = jdbcTemplate.queryForListBean(
				"select * from sys_quartz t", SysQuartz.class);
		for (SysQuartz sq : sysQuartzList) {
			configQuatrz(sq);
		}
	}

	public boolean configQuatrz(SysQuartz sysQuartz) {
		boolean result = false;
		try {
			// 运行时可通过动态注入的scheduler得到trigger
			CronTriggerBean trigger = (CronTriggerBean) scheduler.getTrigger(
					sysQuartz.getTriggername(), Scheduler.DEFAULT_GROUP);
			// 如果计划任务已存在则调用修改方法
			if (trigger != null) {
				change(sysQuartz, trigger);
			} else {
				// 如果计划任务不存在并且数据库里的任务状态为可用时,则创建计划任务
				if (sysQuartz.getState().intValue() == 1) {
					this.createCronTriggerBean(sysQuartz);
				}
			}
			result = true;
		} catch (Exception e) {
			result = false;
			e.printStackTrace();
		}

		return result;
	}

	public void change(SysQuartz sysQuartz, CronTriggerBean trigger)
			throws Exception {
		// 如果任务为可用
		if (sysQuartz.getState().intValue() == 1) {
			// 判断从DB中取得的任务时间和现在的quartz线程中的任务时间是否相等
			// 如果相等，则表示用户并没有重新设定数据库中的任务时间，这种情况不需要重新rescheduleJob
			if (!trigger.getCronExpression().equalsIgnoreCase(
					sysQuartz.getCronexpression())) {
				trigger.setCronExpression(sysQuartz.getCronexpression());
				scheduler.rescheduleJob(sysQuartz.getTriggername(),
						Scheduler.DEFAULT_GROUP, trigger);
				log.info(new Date() + ": 更新" + sysQuartz.getTriggername()
						+ "计划任务");
			}
		} else {
			// 不可用
			scheduler.pauseTrigger(trigger.getName(), trigger.getGroup());// 停止触发器
			scheduler.unscheduleJob(trigger.getName(), trigger.getGroup());// 移除触发器
			scheduler.deleteJob(trigger.getJobName(), trigger.getJobGroup());// 删除任务
			log.info(new Date() + ": 删除" + sysQuartz.getTriggername() + "计划任务");
		}

	}

	/**
	 * 创建/添加计划任务
	 * 
	 * @param sysQuartz
	 *            计划任务配置对象
	 * @throws Exception
	 */
	public void createCronTriggerBean(SysQuartz sysQuartz) throws Exception {
		// 新建一个基于Spring的管理Job类
		MethodInvokingJobDetailFactoryBean mjdfb = new MethodInvokingJobDetailFactoryBean();
		mjdfb.setName(sysQuartz.getJobdetailname());// 设置Job名称

		// mjdfb.setTargetObject(Class.forName(sysQuartz.getTargetobject()).newInstance());//
		// 设置任务类

		mjdfb.setTargetObject(beanFactory.getBean(sysQuartz.getTargetobject()));

		mjdfb.setTargetMethod(sysQuartz.getMethodname());// 设置任务方法
		mjdfb.setConcurrent(sysQuartz.getConcurrent().intValue() != 0); // 设置是否并发启动任务
		mjdfb.afterPropertiesSet();// 将管理Job类提交到计划管理类
		// 将Spring的管理Job类转为Quartz管理Job类
		JobDetail jobDetail = new JobDetail();
		jobDetail = (JobDetail) mjdfb.getObject();
		jobDetail.setName(sysQuartz.getJobdetailname());
		scheduler.addJob(jobDetail, true); // 将Job添加到管理类
		// 新一个基于Spring的时间类
		CronTriggerBean c = new CronTriggerBean();
		c.setCronExpression(sysQuartz.getCronexpression());// 设置时间表达式
		c.setName(sysQuartz.getTriggername());// 设置名称
		c.setJobDetail(jobDetail);// 注入Job
		c.setJobName(sysQuartz.getJobdetailname());// 设置Job名称
		scheduler.scheduleJob(c);// 注入到管理类
		scheduler.rescheduleJob(sysQuartz.getTriggername(),
				Scheduler.DEFAULT_GROUP, c);// 刷新管理类
		log.info(new Date() + ": 新建" + sysQuartz.getTriggername() + "计划任务");
	}

	public Scheduler getScheduler() {
		return scheduler;
	}

	public void setScheduler(Scheduler scheduler) {
		this.scheduler = scheduler;
	}

	public void setBeanFactory(BeanFactory factory) throws BeansException {
		this.beanFactory = factory;

	}

	public BeanFactory getBeanFactory() {
		return beanFactory;
	}

}
